/// ------------------------------------------------------------------------------------------------------------------------------------
///
/// MIT License
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// Copyright (c) 2023 ycz. All rights reserved.
///
/// Created by ycz on  2022/1/2.
///
/// @file  y_comm_m2m.h
///
/// @brief
///     y_comm_m2m 是一种多对多通信服务 可以方便的实现嵌入式设备间的通信
///
/// ------------------------------------------------------------------------------------------------------------------------------------



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 防止当前头文件被重复引用
/// ------------------------------------------------------------------------------------------------------------------------------------

#ifndef _Y_COMM_M2M_H
#define _Y_COMM_M2M_H



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 头文件
/// ------------------------------------------------------------------------------------------------------------------------------------

#include <stdint.h>
#include <stdbool.h>
#include "y_protocol.h"



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 兼容 c++
/// ------------------------------------------------------------------------------------------------------------------------------------

#ifdef __cplusplus
extern "C" {
#endif



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 宏定义
/// ------------------------------------------------------------------------------------------------------------------------------------

#define Y_COMM_M2M_MAJOR       0  ///< 主版本     ( 主架构变化 )
#define Y_COMM_M2M_MINOR       1  ///< 次版本     ( 单个功能增加或修改 )
#define Y_COMM_M2M_PATCH       0  ///< 补丁版本   ( bug 修复 )

#define Y_COMM_RECV_ARR_SIZE   25   ///< 缓存数组大小
#define Y_COMM_SEND_ARR_SIZE   25   ///< 缓存数组大小
#define Y_COMM_FILTER_ARR_SIZE 300  ///< 缓存数组大小  覆盖 15s 清空时间
#define Y_COMM_ACK_ARR_SIZE    100  ///< 缓存数组大小



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 结构体
/// ------------------------------------------------------------------------------------------------------------------------------------

#pragma pack(1)  ///< 设置结构体对齐为 一字节对齐

/// 通信服务参数结构体
typedef struct {
    uint8_t wan_id;          ///< 网络 id
    uint8_t retry_count;     ///< 消息发送重试次数
    uint8_t clear_time_s;    ///< 缓存消息清空时间
    int16_t rssi_threshold;  ///< 无线通信时信号阈值
    bool    is_root;         ///< 是否是根节点
    uint8_t root_mac[6];     ///< 根节点 mac 地址
} COMM_M2M_CONFIG_st;

/// 通信服务句柄结构体
typedef struct {
    COMM_M2M_CONFIG_st config;                                    ///< 参数
    bool               lock;                                      ///< 临界区锁
    uint8_t            nvs_num;                                   ///< nvs 保存编号
    struct {                                                      ///< 占位
        int16_t             rssi;                                 ///< rssi
        PROTOCOL_M2M_V1_st *msg;                                  ///< 消息
    } recv_arr[Y_COMM_RECV_ARR_SIZE];                             ///< 接收消息数组
    struct {                                                      ///< 占位
        uint8_t             count;                                ///< 发送 消息剩余发送次数
        PROTOCOL_M2M_V1_st *msg;                                  ///< 发送 消息指针
    } send_arr[Y_COMM_SEND_ARR_SIZE];                             ///< 发送 消息数组
    struct {                                                      ///< 占位
        uint32_t time;                                            ///< 消息过滤 过滤计时
        uint8_t  num;                                             ///< 消息过滤 编号
        uint8_t  mac[6];                                          ///< 消息过滤  mac
    } filter_arr[Y_COMM_FILTER_ARR_SIZE];                         ///< 消息过滤 数组
    struct {                                                      ///< 占位
        uint32_t time;                                            ///< ack 消息 保存计时
        uint8_t  num;                                             ///< ack 消息编号
        uint8_t  mac[6];                                          ///< ack 消息回应者 mac
    } ack_arr[Y_COMM_ACK_ARR_SIZE];                               ///< ack 消息数组
    uint16_t (*read_cb)(uint8_t *data, uint16_t size);            ///< 底层接收回调类型
    bool (*send_cb)(uint8_t *mac, uint8_t *data, uint16_t size);  ///< 底层发送回调类型
    bool (*business_cb)(PROTOCOL_M2M_V1_st *msg, int16_t rssi);   ///< 业务处理回调类型
} COMM_M2M_st;

#pragma pack()  // 还原默认的对齐方式



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 函数 API
/// ------------------------------------------------------------------------------------------------------------------------------------

void                y_comm_m2m_print_version();                                                                                                                  ///< 打印模块版本号
uint8_t             y_comm_m2m_get_group_wan_id(uint8_t *mac);                                                                                                   ///< 获取组网络 id
bool                y_comm_m2m_parse(COMM_M2M_st *handle, uint8_t *data, uint16_t size, int16_t rssi);                                                           ///< 数据解析
bool                y_comm_m2m_send(COMM_M2M_st *handle, uint8_t *mac, uint8_t dev_type, uint8_t mod_id, uint8_t cmd_id, uint8_t *cmd_data, uint16_t cmd_size);  ///< 发送消息
bool                y_comm_m2m_sync_root(COMM_M2M_st *handle, uint8_t dev_type, uint8_t *mac_list, uint16_t size);                                               ///< 同步 root
bool                y_comm_m2m_sync_time(COMM_M2M_st *handle, uint8_t dev_type, uint64_t time_ms);                                                               ///< 同步时间
void                y_comm_m2m_config_print(COMM_M2M_st *handle, COMM_M2M_CONFIG_st *config);                                                                    ///< 打印参数
COMM_M2M_CONFIG_st *y_comm_m2m_config_get(COMM_M2M_st *handle);                                                                                                  ///< 获取参数
bool                y_comm_m2m_config_set(COMM_M2M_st *handle, COMM_M2M_CONFIG_st *config);                                                                      ///< 设置参数
COMM_M2M_st        *y_comm_m2m_init();                                                                                                                           ///< 初始化
bool                y_comm_m2m_process(COMM_M2M_st *handle, uint32_t time_ms);                                                                                   ///< 任务处理



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 条件编译结尾
/// ------------------------------------------------------------------------------------------------------------------------------------

#ifdef __cplusplus
}
#endif  // __cplusplus 兼容 c++
#endif  // _Y_COMM_M2M_H 防止当前头文件被重复引用